#include "modelTextured.hpp"
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <GL/glut.h>

using namespace std;

modelTextured::modelTextured(){
	nbPoints = nbTexs = nbNodes = 0;
	transform = Matrix<double>::MatrixDiag(4,4);
	transformChanged = true;
}

modelTextured::modelTextured(const unsigned int &sizeP,const unsigned int &sizeT,const unsigned int &sizeN,const string &image){
	nbPoints = sizeP;
	nbTexs = sizeT;
	nbNodes = sizeN;
	
	fileText = image;

	points = Matrix<double>(4,nbPoints);
	texs = Matrix<double>(4,nbTexs);

	nodes = Matrix<int>(3,nbNodes);
	nodesText = Matrix<int>(3,nbNodes);

	transform = Matrix<double>::MatrixDiag(4,4);
	transformChanged = true;
}

modelTextured::~modelTextured(){

}

modelTextured* modelTextured::importFromFile(string file){
	ifstream fichier(file.c_str(), ios::in);
	modelTextured *m = NULL;

	if(fichier){
		unsigned int nbPoint, nbTex, nbNoeud;
		string fileText;
		char c;		//récupération de la parenthese
		
		fichier>>nbPoint>>c>>nbTex>>c>>nbNoeud>>fileText;

		m = new modelTextured(nbPoint,nbTex,nbNoeud,fileText);

		for(unsigned int i = 0; i<nbPoint; i++){
			//cout<<"Point "<<i<<endl;
			fichier>>m->points[0][i];
			fichier>>m->points[1][i];
			fichier>>m->points[2][i];
			m->points[3][i] = 0;
		}

		for(unsigned int i = 0; i<nbTex; i++){
			//cout<<"Tex "<<i<<endl;
			fichier>>m->texs[0][i];
			fichier>>m->texs[1][i];
		}

		for(unsigned int i = 0; i<nbNoeud; i++){
			//cout<<"Node "<<i<<endl;

			fichier>>m->nodes[0][i];
			fichier>>c>>m->nodesText[0][i]>>c;
			fichier>>m->nodes[1][i];
			fichier>>c>>m->nodesText[1][i]>>c;
			fichier>>m->nodes[2][i];
			fichier>>c>>m->nodesText[2][i]>>c;

		}

		fichier.close();
	}
	else{ 
		cerr<<"Erreur ouverture de "<<file<<endl;
	}

	return m;
}

void modelTextured::addMatrix(Matrix<double> &m){
	transform = m * transform ;
	transformChanged = true;
}

void modelTextured::applyMatrix(){
	if(transformChanged){
		pointsTransform =  transform * points ;
		transformChanged = false;
	}
}

void modelTextured::print() {
	int p1,p2,p3;
	cout<<nbPoints<<" points"<<endl;
	cout<<nbTexs<<" texs"<<endl;
	cout<<nbNodes<<" nodes"<<endl;
	for(unsigned int i = 0;i<nbNodes;i++){
		cout<<"Triangle "<<i<<endl;
		p1 = nodesText[0][i];
		p2 = nodesText[1][i];
		p3 = nodesText[2][i];
		cout<<"Point 1 x:"<<texs[0][p1]<<" y:"<<texs[1][p1]<<endl;
		cout<<"Point 2 x:"<<texs[0][p2]<<" y:"<<texs[1][p2]<<endl;
		cout<<"Point 3 x:"<<texs[0][p3]<<" y:"<<texs[1][p3]<<endl;		
	}
	/*
	for(unsigned int i = 0;i<nbNodes;i++){
		cout<<"Triangle "<<i<<endl;
		p1 = nodes[0][i];
		p2 = nodes[1][i];
		p3 = nodes[2][i];
		cout<<"Point 1 x:"<<points[0][p1]<<" y:"<<points[1][p1]<<" z:"<<points[2][p1]<<endl;
		cout<<"Point 2 x:"<<points[0][p2]<<" y:"<<points[1][p2]<<" z:"<<points[2][p2]<<endl;
		cout<<"Point 3 x:"<<points[0][p2]<<" y:"<<points[1][p2]<<" z:"<<points[2][p2]<<endl;		
	}*/
}

vector<double> modelTextured::getNormal(){
	vector<double> norm,p1,p2,p3;

	p1.x = pointsTransform[0][nodes[0][itNode]];
	p1.y = pointsTransform[1][nodes[0][itNode]];
	p1.z = pointsTransform[2][nodes[0][itNode]];

	p2.x = pointsTransform[0][nodes[1][itNode]];
	p2.y = pointsTransform[1][nodes[1][itNode]];
	p2.z = pointsTransform[2][nodes[1][itNode]];

	p3.x = pointsTransform[0][nodes[2][itNode]];
	p3.y = pointsTransform[1][nodes[2][itNode]];
	p3.z = pointsTransform[2][nodes[2][itNode]];

	norm = (p3 - p1) * (p2 - p1);		//Changer selon le sens du repère (à tester)(ça à l'air bon comme ça m'voyez)
	//ou norm = (p2 - p1) * (p3 - p1);

	norm.normalize();//Useless en fait pour l'instant

	return norm;
}


int modelTextured::beginNode(){
	applyMatrix();
	itNode = 0;
	return itNode;
}

int modelTextured::nextNode(){
	itNode++;
	return itNode;
}

bool modelTextured::hasNextNode(){
	//cout<<itPoint<<endl;
	return itNode<nbNodes;
}

vector<double> modelTextured::beginPointByNode(){
	itPoint = 0;
	vector<double> v;
	v.x = pointsTransform[0][nodes[itPoint][itNode]];
	v.y = pointsTransform[1][nodes[itPoint][itNode]];
	v.z = pointsTransform[2][nodes[itPoint][itNode]];
	//cout<<"Node "<<itNode<<" Points "<<itPoint<<endl;
	//cout<<"x "<<v.x<<" y "<<v.y<<" z "<<v.z<<endl;
	return v;
}

vector<double> modelTextured::nextPointByNode(){
	itPoint++;
	vector<double> v;
	v.x = pointsTransform[0][nodes[itPoint][itNode]];
	v.y = pointsTransform[1][nodes[itPoint][itNode]];
	v.z = pointsTransform[2][nodes[itPoint][itNode]];
	//cout<<"Node "<<itNode<<" Points "<<itPoint<<endl;
	//cout<<"x "<<v.x<<" y "<<v.y<<" z "<<v.z<<endl;
	return v;
}

bool modelTextured::hasNextPointByNode(){
	//cout<<itPoint<<endl;
	return itPoint<3;
}

vector<double> modelTextured::beginTexByNode(){
	itTex = 0;
	vector<double> v;
	v.x = texs[0][nodesText[itTex][itNode]];
	v.y = texs[1][nodesText[itTex][itNode]];
	v.z = 0;
	//cout<<"Node "<<itNode<<" Points "<<itPoint<<endl;
	//cout<<"x "<<v.x<<" y "<<v.y<<" z "<<v.z<<endl;
	return v;
}

vector<double> modelTextured::nextTexByNode(){
	itTex++;
	vector<double> v;
	v.x = texs[0][nodesText[itTex][itNode]];
	v.y = texs[1][nodesText[itTex][itNode]];
	v.z = 0;
	//cout<<"Node "<<itNode<<" Points "<<itPoint<<endl;
	//cout<<"x "<<v.x<<" y "<<v.y<<" z "<<v.z<<endl;
	return v;
}

bool modelTextured::hasNextTexByNode(){
	//cout<<itPoint<<endl;
	return itTex<3;
}

vector<double> modelTextured::beginPoint(){
	applyMatrix();
	itPoint = 0;
	vector<double> v;
	v.x = pointsTransform[0][itPoint];
	v.y = pointsTransform[1][itPoint];
	v.z = pointsTransform[2][itPoint];

	cout<<"x "<<v.x<<" y "<<v.y<<" z "<<v.z<<endl;
	return v;
}

vector<double> modelTextured::nextPoint(){
	itPoint++;
	vector<double> v;
	v.x = pointsTransform[0][itPoint];
	v.y = pointsTransform[1][itPoint];
	v.z = pointsTransform[2][itPoint];

	cout<<"x "<<v.x<<" y "<<v.y<<" z "<<v.z<<endl;
	return v;
}

bool modelTextured::hasNextPoint(){
	//cout<<itPoint<<endl;
	return itPoint<nbPoints-1;
}

vector<int> modelTextured::getCentre(){
	vector<int> moy,max,min;
	min.x = max.x = points[0][0];
	min.y = max.y = points[1][0];
	min.z = max.z = points[2][0];
	for(unsigned int i = 1;i<nbPoints;i++){
		if(points[0][i]>max.x) max.x = points[0][i];
		if(points[0][i]<min.x) min.x = points[0][i];
		if(points[1][i]>max.y) max.y = points[1][i];
		if(points[1][i]<min.y) min.y = points[1][i];
		if(points[2][i]>max.z) max.z = points[2][i];
		if(points[2][i]<min.z) min.z = points[2][i];
	}
	moy = (min + max)/2;
	return moy;
}

double modelTextured::getRayon(){
	double max,min;
	min = max = points[0][0];
	for(unsigned int i = 0;i<nbPoints;i++){
		for(unsigned int j = 0;j<3;j++){
			if(points[j][i]>max) max = points[j][i];
			if(points[j][i]<min) min = points[j][i];
		}
	}
	return (max-min)/2;
}

